home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1996 April
/
CHIP 1996 aprilis (CD06).zip
/
CHIP_CD06.ISO
/
hypertxt.arj
/
92
/
SZIMU2.CD
< prev
next >
Wrap
Text File
|
1995-09-14
|
16KB
|
437 lines
@VSzaporodjatok és sokasodjatok...@N
@VSzimuláció 2.@N
Sorozatunk elsô részében tettünk egy kísérletet a nyájas
Olvasó meggyôzésére: a szimuláció fontos, érdekes, mi több
akár szórakoztató is lehet. Megismerkedtünk a folytonos
keretmodellel, s láttunk két egyszerû példát a fizika
területén lehetséges alkalmazásra.
Ezúttal bôvíteni szeretnénk a kínálatot, további
fogásokat veszünk fel az étlapra.
@V""Élünk és meghalunk..."@N
Olvasóink bizonyára találkoztak már egy népesség életkor
szerinti megoszlását ábrázoló grafikonnal, a korfával. Nem
tanulság nélküli egy ilyen ábra elemzése. A mellékelt
grafikonok (melyek a PCGlobe program segítségével, annak
adatai alapján készültek) számos érdekességet tartalmaznak.
Az ábrák Németország, Angola illetve Svédország
népességének életkor szerinti eloszlását mutatják, nemek
szerinti bontásban. Egészen más képet mutat egy ""jóléti
állam", egy -- szegény -- fejlôdô ország, és egy
közép-európai ország korfája. Az értô szem rengeteg tényt
tud belôlük megállapítani, még a közelmúlt történelme is
kiolvasható némi szemlélôdés után. A következôkben egy olyan
modell vázlatos leírását adjuk meg, mely képes lesz e
jelenségek szimulálására.
Gondoskodnunk kell arról, hogy a populációt alkotó
egyedek ""megszülessenek", ""öregedjenek", ""meghaljanak".
Csupa olyan fogalommal fogunk dolgozni, melyek a mindennapi
életbôl ismertek: lesznek generációk, szülôképes
korosztályok (hogy ezt a ronda terminológiát használjuk),
várható életkor stb. Modellünk elsô változatában az alábbi
változókat fogjuk használni:
@KN@N -- az egyedek száma, azaz a populáció létszáma
@KK@N -- a korcsoportok, generációk száma
@KT(I)@N -- megmutatja, hogy az @KI.@N egyed melyik
korcsoporthoz tartozik
@KS(J)@N -- a @KJ.@N korcsoport szaporodási (szülési)
valószínûsége
@KH(J)@N -- a @KJ.@N korcsoport halálozási valószínûsége (tehát
@KH(K)=1@N)
@KDB(J)@N -- a @KJ.@N generáció egyedeinek száma
Szimulációs keretmodellünket (melyet múlt havi
számunkban írtunk le) három ponton kell részleteznünk. Az
adatbeviteli részben nyilván ""kézzel" írandók be @KK, S(J),
H(J)@N értékei, hiszen ezek változtatásával tudunk majd
különbözô futási eredményeket produkálni. A @KT(I)@N értékek
bevitele már kérdéses: jó lenne más és más induló
feltételeket beállítani, de programunk akkor érdekes (és
valószerû), ha sok egyeddel dolgozik. Ehhez azonban több
ezer adatot kellene beírni, tehát célszerûbb a kiindulási
eloszlást véletlenszerûen elôállítani.
Ekkor (gépünk/nyelvünk véletlenszám-generátorától
függôen) egy svéd-jellegû eloszlásból fogunk indulni. Meg
kell gondolnunk, hogy milyen kimenô adat(ok)ra van
szükségünk: kezdetben maradjunk csak a kormegoszlásnál,
melyet megjeleníthetünk numerikusan, de ízlés szerint
grafikusan is. Ezek után már csak a ""szimulációs lépés"
megírása van hátra:
@KSzimulációs_lépés;
J=N;
Ciklus I=1-tôl N-ig;
Ha RND<H(T(I)) akkor
T(I):=0 {meghalt}
DB(T(I)):=DB(T(I))-1;
különben Ha RND<S(T(I)) akkor J:=J+1 {uj}
T(J):=1
DB(0):=DB(0)+1
T(I):=T(I)+1 {öregedés}
DB(T(I):=DB(T(I))-1
DB(T(I+1):=DB(T(I+1))+1
Ciklus vége
Táblázattömörítés;
Eljárás vége;@N
A táblázattömörítés azért szükséges, mert látható módon
elôbb-utóbb igen sok nullát tartanánk nyilván (az
elhalálozott egyedek helyén), miközben a szaporodás miatt
tömbünk kinôné a rendelkezésére álló helyet.
@KTáblázattömörítés;
L:=0;
Ciklus I:=1-tôl J-ig
Ha T(I)>0 akkor L:=L+1
T(L):=T(I)
Ciklus vége
N:=L;
Eljárás vége;@N
Ezek után (már természetesen ha valamilyen nyelven a
programkódot is elôállítottuk) játszhatunk a feltételekkel:
növelhetjük, csökkenthetjük a szaporaság mértékét;
szélesíthetjük, szûkíthetjük a szülni képes generációk
körét; beállíthatjuk mondjuk a fiatalkori halálozás
mértékét, és így tovább. Módunkban áll járványok hatását
megfigyelni: ehhez a szimulációs lépést ki kell bôvítenünk
egy @KJárvány@N nevû eljárással, melynek a lényege az, hogy egy
meghatározott, alacsony (@KY@N-nal jelölt) valószínûségû esetben
a teljes népesség egy jelentôsebb (jele @KZ@N) része
megbetegszik és ennek következtében elpusztul. A @KJárvány@N egy
lehetséges algoritmusa:
@KJárvány;
Ha RND<Y akkor Ciklus I:=1-tôl N-ig
Ha RND<Z akkor T(I):=0
DB(T(I)):=DB(T(I))-1
Ciklus vége
Eljárás vége;@N
Hasonló módon háborúk hatása is vizsgálható, az eltérés
mindössze (a program szempontjából) annyi, hogy bizonyos
korosztályokra nô meg a halálozási valószínûség egy idôre.
Teljesen analóg módon olyan népesség-politikai intézkedések
is modellezhetôk, mint a GYES-GYED bevezetése.
Ha a program kimeneteként csak a globális adatokra
vagyunk kíváncsiak, az algoritmus az alábbiak szerint
jelentôsen leegyszerûsíthetô. Természetesen ennek
megfelelôen az adatbevitel is kényelmesebb, gyorsabb lehet.
(A változók jelölése azonos az elsô algoritmusnál
alkalmazottakkal):
@KSzimulációs_lépés_2;
Ciklus I:=1-tôl K-ig
Ciklus J:=1-tôl DB(I)-ig
Ha RND<H(I) akkor DB(I):=DB(I)-1
különben Ha RND<S(I) akkor D(0):=D(0)+1
Ciklus vége
Ciklus vége
Ciklus L:=K-1-tôl 0-ig
DB(L+1):=DB(L)
Ciklus vége
DB(0):=0
Eljárás vége;@N
@VKüzdelem az életért@N
Az eddigiekben egy faj egyedeivel foglakoztunk, a külsô
tényezôket korlátozottan vettük figyelembe. Pedig a
növekedésnek korlátai vannak: a túlnépesedés, a táplálék
véges mennyisége, ""ellenséges" -- ragadozó -- fajok
jelenléte, stb. A továbbiakban Eigen, Nobel-díjas kémikus
már említett könyve (M. Eigen: A játék) alapján néhány olyan
játékot ismertetünk, melyek a szelekció, a fajok egymás
mellett élésének megértéséhez visznek közelebb.
Ezek a játékok táblán, dobókockával játszandók, elvileg
nincs szükség számítógépre. Látni fogjuk azonban, hogy
technikai nehézségekbe ütköznénk, hiszen több száz, vagy
ezer dobást kellene végrehajtanunk, mondjuk oktaéder alakú
kockával. Másrészt -- lévén a játékoknak pontosan
megfogalmazott szabályrendszerük -- nem okoz nehézséget
számítógépre való átírásuk és így elérhetô például a
mintanagyság növelése is. Csak javasolni tudjuk mindenkinek
az átírást: megdöbbentôen jól modellezik a valós
jelenségeket ezek az igen egyszerû szabályokkal definiálható
játékok.
@VKiválasztódás@N
Négyzet alakú táblán játszunk, melyet kezdetben
""feltöltünk" különbözô színû (az egyszerûbb esetben csak
két színt használva) golyókkal. Ekkor indulnak a dobások,
melyek során -- szigorúan váltakozva -- két szabályt
alkalmazunk:
1. A kisorsolt mezôn lévô golyót levesszük a tábláról.
2. A ""megcímzett" golyót megduplázzuk, azaz a tábla
üres helyére vele azonos színût helyezünk.
Ezt egészen addig ismételjük, míg az egész tábla
egyszínûvé válik. Érdekesebbé tehetô a játék, ha az egyes
színekhez más szelekciós esélyt rendelünk. Ez megvalósítható
a koordináta-sorsolás utáni újabb kockadobással, melynek
eredményétôl függôen veszünk le illetve duplázunk meg
bizonyos színû golyókat.
Például a zöld golyót csak akkor távolítjuk el, ha a
""segéddobás" értéke 1, minden más eredmény (2..6) esetén
duplázunk, s mondjuk a kék golyó esetén pont fordítva járunk
el. A játékban mindig egy szín nyer, de nem biztos, hogy ez
a legnagyobb szelekciós elônnyel rendelkezô szín! A nagy
elôny kiegyenlíthetô egyenlôtlen kiindulási helyzettel, ami
összhangban van azzal a tapasztalattal, hogy ""nagy értékû"
mutánsok a természetben is ritkán fordulnak elô.
@VTúlélés@N
Szintén koordinátázott, négyzet alakú tábla szükséges a
játékhoz, melyet némileg leegyszerûsített formában
ismertetünk, a könnyebb gépi megvalósíthatóság érdekében.
(Az eredeti változathoz tényleges, taktikázó, gondolkodó
játékosok kellenek.) A játékosok különbözô színû golyókkal
rendelkeznek és ""dobásokkal" mezôket sorsolnak ki. A
következô esetek lehetségesek:
1. A mezô üres, akkor egy saját golyó azon elhelyezhetô
(születés).
2. Ha a kisorsolt mezôn saját golyó van, akkor addig
dobhat újra, míg egy olyan kockára nem talál, melyen nincs
saját gombja (reprodukció).
3. ""Ellenséges" mezôt találva, az ott lévô golyó
levehetô, hacsak az nincs túlélô helyzetben (halál).
4. Ha négy azonos színû golyó egy négyzetes tömböt
alkot, akkor túlélô helyzet jött létre, azaz ezek a golyók
akkor sem ""halnak meg", ha az ellenfél által kisorsolódnak.
A játék akkor ér véget, ha minden golyó ""túlélô", s
nyilván az nyert, akinek a legtöbb golyóbisa található a
táblán.
@VKüzdelem@N
Ennek a játéknak Marx György által leírt (Marx György: A
természet játékai) változatát ismertetjük, az Eigen-féle
eredetinél szemléletesebb kerettörténete, játékszabályai
miatt. Világunk ismét egy @KNxN@N-es sakktábla, ahol káposzta
nô, melyet a nyulak fogyasztanak, de a nyulakra rókák
vadásznak. A játék kezdetén világunkat valamilyen eloszlás
szerint benépesítjük @KK, N, R@N betûkkel (vagy aki teheti, neki
tetszô színekkel). Ekkor indul a ""történelem", azaz a
négyzetek kisorsolása egymás után. A kisorsolt négyzeten
végrehajtjuk az alábbi játékszabályok által meghatározott
eseményt:
1. Ha a négyzet üres, rajta káposzta nô.
2. Ha a négyzeten káposzta van, s a négy szomszédos
négyzet egyikén sincs nyúl, a káposzta marad.
3. Ha a kisorsolt négyzeten káposzta van, és valamelyik
szomszédos négyzeten található nyúl, akkor megeszi a
káposztát, s immár jóllakottan szaporodik, azaz a @KK@N betû
helyére @KN@N kerül.
4. Ha a kiválasztott négyzeten nyúl ül és a szomszédban
nincs róka, de van káposzta, akkor a nyúl elfogyasztja a
káposztát (@KN@N marad, @KK@N eltûnik).
5. Ha a kidobott négyzeten nyúl van, de a szomszédokban
se káposzta, se róka, akkor a nyúl éhenhal, azaz az @KN@N betû
eltûnik.
6. Ha a négyzeten nyulat találunk, és a szomszédos mezôk
valamelyikén róka van, akkor a róka a nyulat megeszi, s
""odaszaporodik" a helyére (@KN@N helyébe @KR@N kerül).
7. Ha az aktuális mezôn róka van, és a szomszédban
található egy tapsifüles, akkor a róka életben marad, de a
szegény nyúl nem (@KR@N marad, @KN@N eltûnik).
8. Ha a sorsolt mezôn róka lakik, de a szomszédban nincs
nyúl, a róka éhenhal (@KR@N törlendô).
A fenti szabályokat valósítja meg a listán látható
Pascal nyelvû program.
A betûk váltakozása nem igazán informatív, látványosabb
eredményt kapunk, ha szimulált világunk történéseit
grafikonon jelenítjük meg, egymásra vetítve az egyes fajok
""lélekszámát". Látható a fajok egymásra utaltsága -- az
egyes görbék ciklikusan hullámzanak. A sok káposzta sok
nyulat eredményez, de ez a káposzta mennyiségére van drámai
hatással, ami viszont a nyulak pusztulásához vezet. Eközben
elszaporodtak a rókák is (volt sok nyúl), de a nyulak
pusztulása (melyben a rókák aktív szerepet játszottak) saját
végüket is jelenti. Igazán figyelemre méltó a dologban az,
hogy a talán gyermekdednek tûnô játék által szolgáltatott
grafikon mennyire pontosan fedi a valóságot: a Hudson Öböl
Társaság által begyûjtött róka- és nyúlprémek számának
ingadozása (közel 100 évre visszamenôleg) pontosan ilyen.
Sorozatunk következô részében kicsit mélyebben
vizsgáljuk az Eigen-féle játékok tartalmát, az egyes
növekedési modelleket, illetve az együttélésre készítünk egy
másfajta szimulációt.
@KBánhegyesi Zoltán@N
{$R-,S-}
program nyul_roka_fu;
{Lencsés&Schmideg}
uses crt,graph;
const mx=20; my=20;
ii:array[1..4,1..2] of shortint = ((0,1),(-1,0),(1,0),(-1,0));
var d,i,j,r,n,f,ti,x,y,k,coun,xe,ye,gd,gm:integer;
t:array[1..mx,1..my] of char;
c,ca:char;
graf:boolean;
procedure cha(x,y:integer; duma:string);
begin
gotoxy(x,y);
writeln(duma);
end;
procedure cha2(x,y:integer; duma:integer);
begin
gotoxy(x,y);
writeln(duma,' ');
end;
procedure kepuj;
begin
cha2(48,3,ti);
cha2(48,5,r);
cha2(48,7,n);
cha2(48,9,f);
end;
procedure kep;
begin
for i:=1 to mx do
for j:=1 to my do cha(i,j,t[i,j]);
cha(40,1,'Róka - Nyúl - Fû');
cha(30,3,'Idô : ');
cha(30,5,'Rókák száma : ');
cha(30,7,'Nyulak száma : ');
cha(30,9,'Fû : ');
cha2(60,5,r);
cha2(60,7,n);
cha2(60,9,f);
end;
function xx(xe,ye:integer):char;
begin
if xe=0 then xe:=20;
if ye=0 then ye:=20;
if xe=21 then xe:=1;
if ye=21 then ye:=1;
xx:=t[xe,ye];
end;
procedure szomszed(x,y:integer; ker:char; var k:integer);
begin
k:=0;
repeat
k:=k+1;
until (xx(x+ii[k,1],y+ii[k,2])=ker) or (k>4);
end;
procedure grafikon;
begin
coun:=coun+1;
if coun>70 then begin
cleardevice;
coun:=1;
end;
outtextxy(coun*10,320-r,'R');
outtextxy(coun*10,320-n,'N');
outtextxy(coun*10,320-f,'F');
end;
procedure szim;
begin
x:=random(mx)+1;
y:=random(my)+1;
case t[x,y] of
' ' : begin
t[x,y]:='F'; cha(x,y,t[x,y]);
f:=f+1;
end;
'F' : begin
szomszed(x,y,'N',k);
if k<5 then begin
t[x,y]:='N'; cha(x,y,t[x,y]);
f:=f-1; n:=n+1;
end;
end;
'N' : begin
szomszed(x,y,'R',k);
if k<5 then begin
t[x,y]:='R'; cha(x,y,t[x,y]);
r:=r+1; n:=n-1;
end
else begin
szomszed(x,y,'F',k);
if k<5 then begin
t[x+ii[k,1],y+ii[k,2]]:=' ';
cha(x+ii[k,1],y+ii[k,2],' ');
f:=f-1;
end
else begin
t[x,y]:=' '; cha(x,y,t[x,y]);
n:=n-1;
end;
end;
end;
'R' : begin
szomszed(x,y,'N',k);
if k<5 then begin
t[x+ii[k,1],y+ii[k,2]]:=' ';
cha(x+ii[k,1],y+ii[k,2],' ');
n:=n-1;
end
else begin
t[x,y]:=' '; cha(x,y,t[x,y]);
r:=r-1;
end;
end;
end;
if graf=true then grafikon else kepuj;
end;
procedure bevitel;
begin
clrscr;
write('Rókák száma :='); readln(r);
write('Nyulak száma :='); readln(n);
write('Fûvek száma :='); readln(f);
ti:=0;
end;
procedure berak(ca:char;d:integer);
begin
for i:=1 to d do begin
repeat
x:=random(mx+1);
y:=random(my+1);
until t[x,y]=' ';
t[x,y]:=ca;
end;
end;
procedure feltolt;
begin
for i:=1 to mx do
for j:=1 to my do t[i,j]:=' ';
berak('F',f);
berak('N',n);
berak('R',r);
write('Grafikonon? (I/N)');
c:=readkey;
if (c='I') or (c='i') then begin
graf:=true;
gd:=0; gm:=0;
initgraph(gd,gm,'d:\tp\bgi');
write(chr(7));
end
else graf:=false;
end;
begin
graf:=false;
bevitel;
feltolt;
kep;
repeat
szim;
ti:=ti+1;
until (r<1) or (f<1) or (n<1);
end.